package com.sikaryofficial.backend.manager;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sikaryofficial.backend.config.TenantFilterProperties;
import com.sikaryofficial.backend.constant.ArticleAuditStatusEnum;
import com.sikaryofficial.backend.constant.ArticleSourceEnum;
import com.sikaryofficial.backend.constant.RedisCacheKey;
import com.sikaryofficial.backend.domain.dto.req.BrandSpecialStatisticsReq;
import com.sikaryofficial.backend.domain.dto.resp.MyBalanceDTO;
import com.sikaryofficial.backend.domain.entity.PointsBalance;
import com.sikaryofficial.backend.domain.entity.UserAddress;
import com.sikaryofficial.backend.domain.vo.BrandSpecialStatisticsVO;
import com.sikaryofficial.backend.domain.vo.MyStatisticsVO;
import com.sikaryofficial.backend.domain.vo.OtherStatisticsVO;
import com.sikaryofficial.backend.domain.vo.infomation.ArticleStatisticsVO;
import com.sikaryofficial.backend.domain.vo.mystatics.*;
import com.sikaryofficial.backend.service.IArticleService;
import com.sikaryofficial.backend.service.IMyStatisticsService;
import com.sikaryofficial.backend.service.IPointsBalanceService;
import com.sikaryofficial.backend.service.IPointsDetailService;
import com.sikaryofficial.backend.service.IPrizeRedeemService;
import com.sikaryofficial.backend.service.IUserAddressService;
import com.sikaryofficial.backend.service.article.cache.ArticleCacheService;
import com.sikaryofficial.backend.service.article.cache.ReceivedLikesCacheService;
import com.sikaryofficial.backend.service.brand.cache.BrandTasteCacheService;
import com.sikaryofficial.backend.service.follow.cache.FollowCacheService;
import com.sikaryofficial.backend.service.prize.cache.PrizeActivityCacheService;
import com.sikaryofficial.backend.service.user.UserCacheService;
import com.sikaryofficial.common.core.domain.R;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.RemoteUserService;
import com.sikaryofficial.system.api.domain.SysUser;
import com.sikaryofficial.system.api.model.infomation.FollowCountVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.sikaryofficial.backend.constant.RedisCacheKey.MY_STATISTICS_CACHE;

/**
 * @author : qinjinyuan
 * @desc : 我的个人中心管理服务
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
public class MyStatisticsManager {
    @Autowired
    private IMyStatisticsService myStatisticsService;
    @Autowired
    private IPointsBalanceService pointsBalanceService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private FollowCacheService followCacheService;
    @Autowired
    private ReceivedLikesCacheService receivedLikesCacheService;
    @Resource
    private RemoteUserService remoteUserService;
    @Autowired
    private BrandTasteCacheService brandTasteCacheService;
    @Autowired
    private TenantFilterProperties tenantFilterProperties;
    @Autowired
    private PrizeActivityCacheService activityCacheService;
    @Autowired
    private ArticleCacheService articleCacheService;
    @Autowired
    private UserCacheService userCacheService;
    @Autowired
    private IUserAddressService addressUserService;
    @Autowired
    private IArticleService articleService;
    @Autowired
    private IPointsDetailService pointsDetailService;
    @Autowired
    private IPrizeRedeemService prizeRedeemService;

    private static void buildStaticExt(FansStatics fansStatics, FollowStatics followStatics,
                                       GetLikesStatics receivedLikesStatics,
                                       OtherStatisticsVO statisticsVO) {
        statisticsVO.setFollowers(fansStatics);
        statisticsVO.setFollowing(followStatics);
        statisticsVO.setGetLikes(receivedLikesStatics);
    }

    private static void buildStaticExt(FansStatics fansStatics, FollowStatics followStatics,
                                       GetLikesStatics receivedLikesStatics,
                                       OtherStatisticsVO statisticsVO, OwnerPointsStatics ownerPointFlow) {
        buildStaticExt(fansStatics, followStatics,
                receivedLikesStatics, statisticsVO);
        statisticsVO.setOwnerPointFlow(ownerPointFlow);
    }

    public BrandSpecialStatisticsVO brandSpecialStatistics(BrandSpecialStatisticsReq req) {
        log.info("brandSpecialStatistics-getBrandNo:{}", req.getBrandNo());
        Integer tenantId = tenantFilterProperties.getTenantByBrand(req.getBrandNo());
        if (Objects.isNull(tenantId)) {
            return new BrandSpecialStatisticsVO();
        }
        String cacheKey = MessageFormat.format(RedisCacheKey.BRAND_SPECIAL_STATISTICS_CACHE, req.getBrandNo());
        BrandSpecialStatisticsVO myStatisticsCache = redisService.getCacheObject(cacheKey);
        if (myStatisticsCache == null) {
            myStatisticsCache = queryBrandSpecialStatistics(req.getBrandNo());
            // 缓存1分钟
            redisService.setCacheObject(cacheKey, myStatisticsCache, 2L, TimeUnit.SECONDS);
        }
        return myStatisticsCache;
    }

    /**
     * 获取【我的】相关统计数据
     */
    public MyStatisticsVO getMyStatistics(Long userId) {
        log.info("getMyStatistics-getUserId:{}", userId);
        if (Objects.isNull(userId)) {
            return new MyStatisticsVO();
        }
        String cacheKey = MessageFormat.format(MY_STATISTICS_CACHE, userId);
        MyStatisticsVO myStatisticsCache = redisService.getCacheObject(cacheKey);
        if (myStatisticsCache == null) {
            myStatisticsCache = queryMyStatistics(userId);
            // 缓存1分钟
            redisService.setCacheObject(cacheKey, myStatisticsCache, 1L, TimeUnit.SECONDS);
        }
        return myStatisticsCache;
    }

    private MyStatisticsVO queryMyStatistics(Long userId) {
        FollowCountVO followCountVO = followCacheService.getFollowCount(userId);
        FansStatics fansStatics = FansStatics.builder().hasOpen(true).totalCount(followCountVO.getFansCount()).build();
        FollowStatics followStatics = FollowStatics.builder().hasOpen(true).totalCount(followCountVO.getFriendCount()).build();
        // 收到的点赞数量
        long receivedLikesCount = receivedLikesCacheService.getReceivedLikesCount(userId);
        GetLikesStatics receivedLikesStatics = GetLikesStatics.builder().hasOpen(true).totalCount(receivedLikesCount).build();
        // 个人积分流水
        int ownerPointsCount = pointsDetailService.countOwnerPointsFlow(userId);
        OwnerPointsStatics ownerPointFlow = OwnerPointsStatics.builder().hasOpen(true).totalCount(ownerPointsCount).build();

        MyStatisticsVO statisticsVO = myStatisticsService.queryMyStatistics(userId);
        if (Objects.isNull(statisticsVO)) {
            return initMyStatisticsVO(fansStatics, followStatics, receivedLikesStatics, ownerPointFlow);
        }
        buildStaticExt(fansStatics, followStatics, receivedLikesStatics, statisticsVO, ownerPointFlow);
        buildMyStatisticsData(statisticsVO);
        return statisticsVO;
    }

    private void buildMyStatisticsData(MyStatisticsVO statisticsVO) {
        buildOtherStatisticsData(statisticsVO);
        // 获得礼品
        int prizeRedeemCount = prizeRedeemService.countPrizeRedeem(SecurityUtils.getUserId());
        int activityPrizeCount = prizeRedeemService.countActivityResult(SecurityUtils.getUserId());
        statisticsVO.setPrize(PrizeRedeemStatics.builder().hasOpen(true)
                .totalCount(prizeRedeemCount + activityPrizeCount)
                .build());
        /**
         * 设置很多数据结构
         */
        // 评价
        statisticsVO.setReviews(CommentsStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getReplyCount() + statisticsVO.getEvaluateCount())
                .replyCount(statisticsVO.getReplyCount())
                .evaluateCount(statisticsVO.getEvaluateCount())
                .build());
        // 收藏
        statisticsVO.setCollection(CollectionStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getStoreCollectionCount() + statisticsVO.getProductCollectionCount() + statisticsVO.getActivityCollectionCount())
                .productCollectionCount(statisticsVO.getProductCollectionCount())
                .storeCollectionCount(statisticsVO.getStoreCollectionCount())
                .activityCollectionCount(statisticsVO.getActivityCollectionCount())
                .build());
        // 点赞
        statisticsVO.setLike(LikesStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getLikesEvaluateNum() + statisticsVO.getLikesProductNum())
                .likesEvaluateNum(statisticsVO.getLikesEvaluateNum())
                .likesProductNum(statisticsVO.getLikesProductNum())
                .build());
        // 举报
        long accepting = statisticsVO.getReportCount() - statisticsVO.getReportAcceptedCount();
        statisticsVO.setReport(ReportStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getReportCount())
                .accepted(statisticsVO.getReportAcceptedCount())
                .accepting(accepting < 0 ? 0 : accepting)
                .build());
        // 预约
        long reservedCount = statisticsVO.getReservedCount() - statisticsVO.getExpireCount();
        statisticsVO.setReservation(ReservationStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getReservedCount() + statisticsVO.getAwardsCount())
                .reservedCount(reservedCount < 0 ? 0 : reservedCount)
                .expireCount(statisticsVO.getExpireCount())
                .awardsCount(statisticsVO.getAwardsCount())
                .build());
        // 分享
        statisticsVO.setSharing(SharingStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getStoreSharedCount() + statisticsVO.getProductSharedCount())
                .storeSharedCount(statisticsVO.getStoreSharedCount())
                .productSharedCount(statisticsVO.getProductSharedCount())
                .build());
        // 工单
        statisticsVO.setAfterSale(WorkOrderStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getWorkOrderCount())
                .build());
    }

    private MyStatisticsVO initMyStatisticsVO(FansStatics fansStatics, FollowStatics followStatics, GetLikesStatics receivedLikesStatics
            , OwnerPointsStatics ownerPointFlow) {
        MyStatisticsVO vo = new MyStatisticsVO();
        buildStaticExt(fansStatics, followStatics, receivedLikesStatics, vo, ownerPointFlow);
        vo.setOwnerPointFlow(ownerPointFlow);
        vo.setWorks(WorksStatics.builder().hasOpen(true).totalCount(0).dynamicCount(0).longCount(0).reelsCount(0).build());
        vo.setReviews(CommentsStatics.builder().hasOpen(true).totalCount(0).replyCount(0).evaluateCount(0).build());
        vo.setCollection(CollectionStatics.builder().hasOpen(true).totalCount(0).productCollectionCount(0).storeCollectionCount(0).activityCollectionCount(0).build());
        vo.setLike(LikesStatics.builder().hasOpen(true).totalCount(0).likesEvaluateNum(0).likesProductNum(0).build());
        vo.setReport(ReportStatics.builder().hasOpen(true).totalCount(0).accepted(0).accepting(0).build());
        vo.setReservation(ReservationStatics.builder().hasOpen(true).totalCount(0).reservedCount(0).expireCount(0).awardsCount(0).build());
        vo.setSharing(SharingStatics.builder().hasOpen(true).totalCount(0).storeSharedCount(0).productSharedCount(0).build());
        vo.setAfterSale(WorkOrderStatics.builder().hasOpen(true).totalCount(0).build());
        vo.setPrize(PrizeRedeemStatics.builder().hasOpen(true).totalCount(0).build());
        return vo;
    }

    /**
     * 品牌专栏统计
     * <p>
     * 1、活动统计
     * 2、产品统计 （从缓存进行统计）
     * 3、文章统计 （已审核通过的文章）
     *
     * @param brandNo
     * @return
     */
    private BrandSpecialStatisticsVO queryBrandSpecialStatistics(String brandNo) {
        Integer tenantId = tenantFilterProperties.getTenantByBrand(brandNo);
        BrandSpecialStatisticsVO statisticsVO = new BrandSpecialStatisticsVO();
        // 活动统计
        ActivityStatics activity = ActivityStatics.builder().hasOpen(true).totalCount(activityCacheService.getActivityCountByTenantId(tenantId)).build();
        // 产品统计
        ProductStatics product = ProductStatics.builder().hasOpen(true).totalCount(brandTasteCacheService.getBrandTasteCount(tenantId)).build();
        statisticsVO.setActivity(activity);
        statisticsVO.setProduct(product);
        ArticleStatisticsVO articleStatistics = articleCacheService.getArticleStatistics(brandNo);
        if (Objects.isNull(articleStatistics)) {
            statisticsVO.setWorks(WorksStatics.builder().hasOpen(true).totalCount(0).dynamicCount(0).longCount(0).reelsCount(0).build());
            return statisticsVO;
        }
        /**
         * 文章 统计 ： 动态与长文
         */
        statisticsVO.setWorks(WorksStatics.builder().hasOpen(true).totalCount(articleStatistics.getDynamicNum() + articleStatistics.getLongEssayNum() +
                        articleStatistics.getReelsNum()).reelsCount(articleStatistics.getReelsNum()).dynamicCount(articleStatistics.getDynamicNum())
                .longCount(articleStatistics.getLongEssayNum()).build());
        return statisticsVO;
    }

    public OtherStatisticsVO otherStatistics(Long userId) {
        FollowCountVO followCountVO = followCacheService.getFollowCount(userId);
        FansStatics fansStatics = FansStatics.builder().hasOpen(true).totalCount(followCountVO.getFansCount()).build();
        FollowStatics followStatics = FollowStatics.builder().hasOpen(true).totalCount(followCountVO.getFriendCount()).build();

        long receivedLikesCount = receivedLikesCacheService.getReceivedLikesCount(userId);
        GetLikesStatics receivedLikesStatics = GetLikesStatics.builder().hasOpen(true).totalCount(receivedLikesCount).build();

        List<ArticleStatisticsVO> articleStatisticsVOS = articleService.articleContentTypeStatic(ArticleSourceEnum.USER.getCode(), ArticleAuditStatusEnum.APPROVED.getCode(), userId);
        if (CollUtil.isEmpty(articleStatisticsVOS)) {
            return initOtherStatisticsVO(fansStatics, followStatics, receivedLikesStatics);
        }
        OtherStatisticsVO statisticsVO = new OtherStatisticsVO();
        buildStaticExt(fansStatics, followStatics, receivedLikesStatics, statisticsVO);
        // 构建文章相关统计
        buildArticleStatistics(statisticsVO, articleStatisticsVOS);
        return statisticsVO;
    }

    private void buildArticleStatistics(OtherStatisticsVO statisticsVO, List<ArticleStatisticsVO> statisticsVOList) {
        ArticleStatisticsVO articleStatisticsVO = statisticsVOList.iterator().next();
        if (Objects.isNull(articleStatisticsVO)) {
            return;
        }
        /**
         * 文章 统计 ： 动态与长文
         */
        statisticsVO.setWorks(WorksStatics.builder().hasOpen(true)
                .totalCount(articleStatisticsVO.getDynamicNum() + articleStatisticsVO.getLongEssayNum() + articleStatisticsVO.getReelsNum())
                .dynamicCount(articleStatisticsVO.getDynamicNum())
                .longCount(articleStatisticsVO.getLongEssayNum())
                .reelsCount(articleStatisticsVO.getReelsNum())
                .build());
    }

    private void buildOtherStatisticsData(OtherStatisticsVO statisticsVO) {
        /**
         * 文章 统计 ： 动态与长文
         */
        statisticsVO.setWorks(WorksStatics.builder().hasOpen(true)
                .totalCount(statisticsVO.getDynamicCount() + statisticsVO.getLongCount() + statisticsVO.getReelsCount())
                .dynamicCount(statisticsVO.getDynamicCount())
                .longCount(statisticsVO.getLongCount())
                .reelsCount(statisticsVO.getReelsCount())
                .build());
    }

    private OtherStatisticsVO initOtherStatisticsVO(FansStatics fansStatics, FollowStatics followStatics, GetLikesStatics receivedLikesStatics) {
        OtherStatisticsVO statisticsVO = new OtherStatisticsVO();
        buildStaticExt(fansStatics, followStatics, receivedLikesStatics, statisticsVO);
        statisticsVO.setWorks(WorksStatics.builder().hasOpen(true).totalCount(0).dynamicCount(0).longCount(0).reelsCount(0).build());
        return statisticsVO;
    }

    public MyBalanceDTO getMyBalance() {
        MyBalanceDTO dto = new MyBalanceDTO();
        if (Objects.equals(SecurityUtils.getUserId(), 0L)) {
            return dto;
        }
        getUserInfo(SecurityUtils.getUserId(), dto);
        PointsBalance pointsBalance = pointsBalanceService.getPointsBalanceByUserId(SecurityUtils.getUserId());
        Optional.ofNullable(pointsBalance).ifPresent(balance -> dto.setBalance(balance.getBalance()));
        // 是否填写收货地址
        int count = addressUserService.count(new LambdaQueryWrapper<UserAddress>()
                .eq(UserAddress::getCreatedBy, SecurityUtils.getUserId())
                .eq(UserAddress::getDeletedVersion, 0L)
        );
        dto.setHasShippingAddress(count > 0);
        return dto;
    }

    /**
     * @param authId 作者ID
     * @return
     */
    public MyBalanceDTO otherBalance(Long authId) {
        MyBalanceDTO dto = new MyBalanceDTO();
        // 积分余额
        PointsBalance pointsBalance = pointsBalanceService.getPointsBalanceByUserId(authId);
        Optional.ofNullable(pointsBalance).ifPresent(balance -> dto.setBalance(balance.getBalance()));
        // 查看当前用户是否是作者的粉丝
        dto.setHasFollow(followCacheService.hasFollow(SecurityUtils.getUserId(), authId));
        getUserInfo(authId, dto);
        return dto;
    }

    /**
     * 设置 用户信息 及缓存更新
     *
     * @param authId
     * @param dto
     */
    private void getUserInfo(Long authId, MyBalanceDTO dto) {
        if (Objects.isNull(authId)) {
            return;
        }
        SysUser user = userCacheService.getSysUser(authId);
        if (Objects.nonNull(user)) {
            dto.setBackground(user.getBackImg());
            dto.setAvatar(user.getAvatar());
            dto.setUserName(user.getUserName());
            dto.setNickName(user.getNickName());
            return;
        }
        R<SysUser> result1 = remoteUserService.getUserByUserId(authId);
        if (Objects.isNull(result1) || Objects.isNull(result1.getData())) {
            return;
        }
        SysUser sysUser = result1.getData();
        if (Objects.nonNull(sysUser)) {
            // 填充头像数据
            dto.setAvatar(sysUser.getAvatar());
            // 个人背景图片
            dto.setBackground(sysUser.getBackImg());
            // 用户名
            dto.setUserName(sysUser.getUserName());
            dto.setNickName(sysUser.getNickName());
            log.info("更新缓存数据");
            userCacheService.setSysUser(authId, sysUser);
        }
    }
}